package com.asset.crm.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;


import com.asset.crm.client.GreetingService;
import com.asset.crm.dao.HibernateUtil;
import com.asset.crm.domain.Contact;
import com.asset.crm.domain.Employee;
import com.asset.crm.domain.Invoice;
import com.asset.crm.domain.InvoiceItem;
import com.asset.crm.domain.InvoiceItemParent;
import com.asset.crm.domain.InvoiceService;
import com.asset.crm.domain.InvoiceSku;
import com.asset.crm.domain.InvoiceTax;
import com.asset.crm.domain.Login;
import com.asset.crm.domain.StockSku;
import com.asset.crm.shared.ContactDTO;
import com.asset.crm.shared.EmployeeDTO;
import com.asset.crm.shared.FieldVerifier;
import com.asset.crm.shared.InvoiceDTO;
import com.asset.crm.shared.ServiceItemDTO;
import com.asset.crm.shared.SkuDTO;
import com.asset.crm.shared.SkuItemDTO;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
    GreetingService {
	//ContactDaoImpl contactDaoImpl = new ContactDaoImpl();
	public String getContact() {
		
//		Contact contact = new Contact();
//		contact.setDate(new Date());
//		contact.setDateCreated(new Date());
//		contact.setDateModified(new Date());
//		contact.setEmail("dev.ahmed.gamal@gmail.com");
//		contact.setfName("ahmed G");
//		contact.setGender("mail");
		 System.out.println("Maven + Hibernate + MySQL");
	        Session session = HibernateUtil.getSessionFactory().openSession();
	        
	        session.beginTransaction();
	        Contact contact = new Contact();
			contact.setDate(new Date());
			contact.setDateCreated(new Date());
			contact.setDateModified(new Date());
			contact.setEmail("dev.ahmed.gamal@gmail.com");
			contact.setfName("ahmed G");
			contact.setGender("mail");
			//contactDaoImpl.saveOrUpdate(contact);
			session.saveOrUpdate(contact);
	        session.getTransaction().commit();
		
		return "hiiiiiiiiiiiiiiiii";
	}
  public String greetServer(String input) throws IllegalArgumentException {
    // Verify that the input is valid.
    if (!FieldVerifier.isValidName(input)) {
      // If the input is not valid, throw an IllegalArgumentException back to
      // the client.
      throw new IllegalArgumentException(
          "Name must be at least 4 characters long");
    }

    String serverInfo = getServletContext().getServerInfo();
    String userAgent = getThreadLocalRequest().getHeader("User-Agent");

    // Escape data from the client to avoid cross-site script vulnerabilities.
    input = escapeHtml(input);
    userAgent = escapeHtml(userAgent);

    return "Hello, " + input + "!<br><br>I am running " + serverInfo
        + ".<br><br>It looks like you are using:<br>" + userAgent;
  }

  /**
   * Escape an html string. Escaping data received from the client helps to
   * prevent cross-site script vulnerabilities.
   *
   * @param html the html string to escape
   * @return the escaped string
   */
  private String escapeHtml(String html) {
    if (html == null) {
      return null;
    }
    return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(
        ">", "&gt;");
  }
  public static void main(String[] args) {
	  GreetingServiceImpl greetingServiceImpl =new GreetingServiceImpl();
	 System.out.println(greetingServiceImpl.searchSkus("White").size());
	  //Employee employee =  greetingServiceImpl.login("ww@ww.com", "123qwe", "ww");
//	  /System.out.println("Donnnnnnnnnnnnnnnnnnnnnnnnnnne"+employee.getEmail());
}
@Override
public EmployeeDTO login(String email, String password, String companyName) {
	Session session= HibernateUtil.getSessionFactory().openSession();
	Query query = session.createQuery("from Login e where e.email = :email and e.password = :password  ");
	query.setParameter("email", email);
	query.setParameter("password", password);
	//query.setParameter("companyName", companyName);
	Transaction transaction = session.beginTransaction();
	 List<Login> list =  query.list();
	 if(list != null){
		 Employee employee = (Employee) session.get(Employee.class, list.get(0).getId());
		 transaction.commit();
		 EmployeeDTO employeeDTO = cloneObj(employee);
		 return employeeDTO;
	 }else{
		 transaction.rollback();
	 }
	return null;
}
private EmployeeDTO cloneObj(Employee employee){
	EmployeeDTO employeeDTO = new EmployeeDTO();
	employeeDTO.setEmail(employee.getEmail());
	employeeDTO.setfName(employee.getfName());
	employeeDTO.setlName(employee.getlName());
	return employeeDTO;
}
@SuppressWarnings("unchecked")
@Override
public Set<SkuDTO> searchSkus(String skuName) {
	Session session= HibernateUtil.getSessionFactory().openSession();
//	Query query = session.createQuery("from StockSku where name= :name");
//	String string =  skuName+"%";
//	query.setParameter("name", string);
//	System.out.println(query.toString());
	Criteria criteria = session.createCriteria(StockSku.class);
	criteria.add(Restrictions.like("name", "%"+skuName+"%"));
	//System.out.println(criteria.list().size());
	Transaction transaction = session.beginTransaction();
	 List<StockSku>list  =new ArrayList<StockSku>();
	 list = criteria.list();
	// System.out.println("li"+list.size());
	 transaction.commit();
	if(list != null && list.size() >0){
		Set<SkuDTO> skuDTOs = cloneObj(list);
		///Collections
		for (SkuDTO skuDTO : skuDTOs) {
			System.out.println("======================= "+skuDTO.getId());
		}
		return skuDTOs;
	}
	return new TreeSet<SkuDTO>();
}
private Set<SkuDTO> cloneObj(List<StockSku> stockSkus){
	Set<SkuDTO>skuDTOs = new TreeSet<SkuDTO>();
	for(StockSku stockSku:stockSkus){
		SkuDTO skuDTO = new SkuDTO();
		skuDTO.setCode(stockSku.getCode());
		skuDTO.setId(stockSku.getId().toString());
		skuDTO.setPrice(stockSku.getPrice());
		skuDTO.setQuantity(stockSku.getQuantity());
		skuDTO.setSale(stockSku.getSale());
		skuDTO.setSkuName(stockSku.getName());
		skuDTOs.add(skuDTO);
	}
	return skuDTOs;
}
@SuppressWarnings("unchecked")
@Override
public Set<ContactDTO> searchContact(String contact) {
	// TODO Auto-generated method stub
	 System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>searchContact");
	Session session= HibernateUtil.getSessionFactory().openSession();
	Criteria criteria = session.createCriteria(Contact.class);
	criteria.add(Restrictions.like("fName", "%"+contact+"%"));
	//System.out.println(criteria.list().size());
	Transaction transaction = session.beginTransaction();
	 System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	 List<Contact>list  =new ArrayList<Contact>();
	 System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+list.size());
	 try{
	 list = criteria.list();

	 System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+list.size());
	 transaction.commit();
	if(list != null && list.size() >0){
		Set<ContactDTO> contactDTOs = cloneContct(list);
		System.out.println("");
		return contactDTOs;
	}
	 }catch(Exception exception){
		 exception.printStackTrace();
	 }
	return new TreeSet<ContactDTO>();
}
private Set<ContactDTO> cloneContct(List<Contact> list) {
	Set<ContactDTO> contactDTOs = new TreeSet<ContactDTO>();
	for(Contact contact:list){
		ContactDTO contactDTO = new ContactDTO();
		if(contact.getCreator() != null){
			contactDTO.setCreator(contact.getCreator().getEmail());
		}
		if(contact.getDateCreated() != null){
			contactDTO.setDateCreated(contact.getDateCreated().toString());
		}
		if(contact.getDateModified() != null){
			contactDTO.setDateModified(contact.getDateModified().toString());
		}
		if(contact.getEmail() != null){
			contactDTO.setEmail(contact.getEmail());
		}
		if(contact.getfName() != null){
			contactDTO.setfName(contact.getfName());
		}
		if(contact.getId() != null){
			contactDTO.setId(contact.getId().toString());
		}
		
		if(contact.getlName() != null){
			contactDTO.setlName(contact.getlName());
		}
		if(contact.getMobile() != null){
			contactDTO.setMobile(contact.getMobile());
		}
		if(contact.getParentId() != null){
			contactDTO.setParentId(contact.getParentId().toString());
		}
		
		if(contact.getParentName() != null){
			contactDTO.setParentName(contact.getParentName());
		}
		if(contact.getPhone() != null){
			contactDTO.setPhone(contact.getPhone());
		}
		if(contact.getTitle() != null){
			contactDTO.setTitle(contact.getTitle());
		}
		contactDTOs.add(contactDTO);
	}
	return contactDTOs;
}
	@SuppressWarnings("unused")
	@Override
	public void saveInvoice(InvoiceDTO invoiceDTO) {
		
		
		Session session =  HibernateUtil.getSessionFactory().openSession();
		List<InvoiceSku> invoiceSkus = getInvoiceSku(invoiceDTO,session);
		List<InvoiceService> invoiceServices =  getInvoiceService(invoiceDTO,session);
		Invoice invoice = getInvoiceInvoice(invoiceDTO,session);
		Transaction tx = session.beginTransaction();
		try{
		Contact contact = (Contact)session.get(Contact.class, Integer.parseInt(invoiceDTO.getContact()));
		invoice.setContact(contact);
		Query query = session.createQuery("from Employee e where e.email = :email ");
		query.setParameter("email", invoiceDTO.getOwner());
		Employee owner = (Employee)query.list().get(0);
		invoice.setOwner(owner);
		session.saveOrUpdate(invoice);
		for(InvoiceSku invoiceSku :invoiceSkus){
			invoiceSku.setOwner(owner);
			Query query2 = session.createQuery("from StockSku e where e.code = :code");
			query2.setParameter("code", invoiceSku.getCode());
			StockSku stockSku = (StockSku) query2.list().get(0);
			invoiceSku.setStockSku(stockSku);
			InvoiceItemParent invoiceItemParent = (InvoiceItemParent)invoiceSku;
			session.saveOrUpdate(invoiceItemParent);
			session.saveOrUpdate(invoiceSku);
			InvoiceItem invoiceItem = new InvoiceItem();
			invoiceItem.setInvoice(invoice);
			invoiceItem.setInvoiceItemParent(invoiceItemParent);
			session.saveOrUpdate(invoiceItem);
		}
		for(InvoiceService invoiceService :invoiceServices){
			invoiceService.setOwner(owner);
			InvoiceItemParent invoiceItemParent = (InvoiceItemParent)invoiceService;
			session.saveOrUpdate(invoiceItemParent);
			session.saveOrUpdate(invoiceService);
			InvoiceItem invoiceItem = new InvoiceItem();
			invoiceItem.setInvoice(invoice);
			invoiceItem.setInvoiceItemParent(invoiceItemParent);
			session.saveOrUpdate(invoiceItem);
		}
		tx.commit();
		}catch (Exception e) {
			// TODO: handle exception
			tx.rollback();
			e.printStackTrace();
		}
	}
	private List<InvoiceSku>  getInvoiceSku(InvoiceDTO invoiceDTO,Session session){
		List<SkuItemDTO> skuItemDTOs =new ArrayList<SkuItemDTO>();
		skuItemDTOs = invoiceDTO.getSkuItemDTOs();
		List<InvoiceSku> invoiceSkus = new ArrayList<InvoiceSku>();
		if(skuItemDTOs != null && skuItemDTOs.size()>0){
			for(SkuItemDTO skuItemDTO :skuItemDTOs){
				InvoiceSku invoiceSku =  new InvoiceSku();
				invoiceSku.setCode(skuItemDTO.getCode());
				invoiceSku.setDiscount(skuItemDTO.getDiscount());
				invoiceSku.setName(skuItemDTO.getName());
				invoiceSku.setQuantity(skuItemDTO.getQuantity());
				if(!skuItemDTO.getTaxOne().equalsIgnoreCase("0")){
					InvoiceTax invoiceTax = (InvoiceTax)session.get(InvoiceTax.class, Integer.parseInt(skuItemDTO.getTaxOne()));
					invoiceSku.setTaxOne(invoiceTax);
				}
				if(!skuItemDTO.getTaxTwo().equalsIgnoreCase("0")){
					InvoiceTax invoiceTax = (InvoiceTax)session.get(InvoiceTax.class, Integer.parseInt(skuItemDTO.getTaxTwo()));
					invoiceSku.setTaxTwo(invoiceTax);
				}
				invoiceSku.setTotalPrice(skuItemDTO.getTotalPrice());
				invoiceSku.setPrice(skuItemDTO.getPrice());
				invoiceSku.setDateCreated(new Date());
				invoiceSku.setDateModified(new Date());
				invoiceSku.setIsDeleted(false);
				invoiceSkus.add(invoiceSku);
			}
		}
		return invoiceSkus;
		
	}
	private List<InvoiceService>  getInvoiceService(InvoiceDTO invoiceDTO,Session session){
		List<ServiceItemDTO> serviceItemDTOs = new ArrayList<ServiceItemDTO>();
		serviceItemDTOs= invoiceDTO.getServiceItemDTOs();
		List<InvoiceService> invoiceServices = new ArrayList<InvoiceService>();
		if(serviceItemDTOs != null && serviceItemDTOs.size() > 0){
			for(ServiceItemDTO serviceItemDTO:serviceItemDTOs){
				InvoiceService invoiceService = new InvoiceService();
				invoiceService.setCostPerHour(serviceItemDTO.getCostPerHour());
				invoiceService.setDiscount(serviceItemDTO.getDiscount());
				invoiceService.setHours(serviceItemDTO.getHours());
				invoiceService.setName(serviceItemDTO.getName());
				if(!serviceItemDTO.getTaxOne().equalsIgnoreCase("0")){
					InvoiceTax invoiceTax = (InvoiceTax)session.get(InvoiceTax.class, Integer.parseInt(serviceItemDTO.getTaxOne()));
					invoiceService.setTaxOne(invoiceTax);
				}
				if(!serviceItemDTO.getTaxTwo().equalsIgnoreCase("0")){
					InvoiceTax invoiceTax = (InvoiceTax)session.get(InvoiceTax.class, Integer.parseInt(serviceItemDTO.getTaxTwo()));
					invoiceService.setTaxTwo(invoiceTax);
				}
				invoiceService.setTotalCost(serviceItemDTO.getTotalCost());
				invoiceService.setCode(serviceItemDTO.getCode());
				invoiceService.setDateCreated(new Date());
				invoiceService.setDateModified(new Date());
				invoiceService.setIsDeleted(false);
				invoiceServices.add(invoiceService);
			}
		}
		return invoiceServices;
	}
	private Invoice getInvoiceInvoice(InvoiceDTO invoiceDTO,Session session){
		Invoice invoice = new Invoice();
		invoice.setCode(invoiceDTO.getCode());
		invoice.setDateCreated(new Date());
		invoice.setDiscount(invoiceDTO.getDiscount());
		invoice.setIsDeleted(false);
		invoice.setTotalPrice(invoiceDTO.getTotalPrice());
		return invoice;
	}
}
